<template>
  <teleport :to="to">
    <transition name="fade"
      ><div ref="userInfoRef" class="recordUserInfo" v-if="modelValue">
        <template v-if="showContent">
          <div class="recordUserInfo-header">
            <div style="display: inline-block" v-if="userInfos">
              <user-info :user-data="userInfos" @open-modal="openModal"></user-info>
            </div>
            <div
              v-if="userId !== user.userId && isFriend && showMore"
              class="recordUserInfo-header__more"
            >
              <SvgIcon
                icon-class="more"
                popper-class="recordUserInfo-more--icon"
                @click="showMenu = !showMenu"
              />
            </div>
          </div>
          <template v-if="userId !== user.userId && (userInfos as any).remark">
            <transition name="fade">
              <dl ref="userInfoMenuRef" v-show="showMenu" class="recordUserInfo-menu">
                <dt @click="openSetup(0)">设置备注和标签</dt>
                <dt @click="openSetup(1)">设置朋友圈权限</dt>
              </dl></transition
            >
            <div class="recordUserInfo-main">
              <span class="recordUserInfo-main__name">备注名</span>
              <span
                class="recordUserInfo-main__value"
                >{{ (userInfos as any).remark }}</span
              >
              <div
                class="recordUserInfo-main__tag clearfix"
                v-if="(userInfos as any).group"
              >
                <span class="recordUserInfo-main__name">分组</span>
                <span
                  class="recordUserInfo-main__value"
                  >{{ (userInfos as any).group }}</span
                >
              </div>
              <div
                class="recordUserInfo-main__tag clearfix"
                v-if="(userInfos as any).disabledOtherLook || (userInfos as any).disabledSelfLook"
              >
                <span class="recordUserInfo-main__name">朋友权限</span>
                <span class="recordUserInfo-main__value">{{
                  (userInfos as any).disabledOtherLook && !(userInfos as any).disabledSelfLook
                    ? "不让对方看"
                    : !(userInfos as any).disabledOtherLook && (userInfos as any).disabledSelfLook
                    ? "不看对方"
                    : "既不看对方也不让对方看"
                }}</span>
              </div>
            </div></template
          ></template
        >
        <div class="recordUserInfo-loading flex" v-else-if="isRequesting">
          <SvgIcon icon-class="loadingGray" popper-class="loadingIcon spinMess" />
        </div>
        <div class="recordUserInfo-error" v-else-if="isError">
          请求失败，点击
          <span @click="requestInfos">重试</span>
        </div>
      </div></transition
    ></teleport
  >
  <template v-if="user.userId !== userId && isFriend && showMore"
    ><setup
      :to="setupTo"
      v-model="showSetup"
      :type="setupState"
      v-model:info-rem-group="theInfoRemGroup"
      v-model:info-permission="theInfoPermission"
      :other-id="userId"
      :width="dialogWid"
      @success="success"
    ></setup
  ></template>
  <Modal v-model="showModal">
    <img class="img-browser" :src="imgSrc" alt="" />
  </Modal>
</template>

<script lang="ts" setup>
import { ref, watch, watchEffect, computed } from "vue";
import userInfo from "@/components/userInfo.vue";
import { useUserPinia } from "@/pinia/user";
import { storeToRefs } from "pinia";
import Modal from "@/components/ui-components/modal.vue";
import setup from "./setup.vue";
import { useFriendPinia } from "@/pinia/friend";
import { source, refreshAxios } from "@/plugins/http";

const props = withDefaults(
  defineProps<{
    modelValue: boolean;
    userId: string;
    to?: string;
    setupTo?: string;
    width?: number | string;
    isFriend?: boolean;
    showMore?: boolean;
    isFriendDynamic?: boolean;
  }>(),
  {
    to: "#chat-col__messages",
    setupTo: ".chat-box",
    width: "32%",
    isFriend: true,
    showMore: true,
    isFriendDynamic: true,
  }
);
const emits = defineEmits<{
  (e: "update:modelValue", show: boolean): void;
  (e: "updatePosition"): void;
  (
    e: "success",
    payload: { userId: string; type: 0 | 1; remark?: string; disabledSelfLook?: boolean }
  ): void;
}>();

const friendStore = useFriendPinia();
const { user } = storeToRefs(useUserPinia());
const userInfoRef = ref<HTMLElement>();

/**
 * 对话框的宽度
 */
const dialogWid = ref<string>("");

watchEffect(() => {
  if (props.width) {
    if (!isNaN(+props.width)) dialogWid.value = `${props.width}px`;
    else if (
      typeof props.width === "string" &&
      (/^\d+%$/.test(props.width) || /^\d+px$/.test(props.width))
    )
      dialogWid.value = props.width;
  } else dialogWid.value = "40%";
});

/**
 * 是否正在请求用户信息数据
 */
const isRequesting = ref<boolean>(false);
/**
 * 请求是否出错
 */
const isError = ref<boolean>(false);
/**
 * 是否显示正文内容
 */
const showContent = ref<boolean>(false);
/**
 * 该用户的用户信息
 */
const userInfos = computed(() => {
  if (props.userId) {
    if (props.userId === user.value.userId) return user.value;
    else if (friendStore.friendsInfos.has(props.userId))
      return Object.assign(friendStore.friendsInfos.get(props.userId)!, {
        userId: props.userId,
      });
  }
});
/**
 * 对方的备注和分组
 */
const theInfoRemGroup = ref<{ remark: string; group: string }>({
  remark: "",
  group: "",
});
/**
 * 对对方的朋友圈权限
 */
const theInfoPermission = ref<Permission>({
  disabledOtherLook: false,
  disabledSelfLook: false,
});

// 根据传入的userId设置其好友的信息
const setInfo = (userId: string) => {
  const data = friendStore.friendsInfos.get(userId)!;
  Object.keys(theInfoRemGroup.value).forEach(
    (key) => ((theInfoRemGroup.value as any)[key] = (data as any)[key])
  );
  Object.keys(theInfoPermission.value).forEach(
    (key) => ((theInfoPermission.value as any)[key] = (data as any)[key])
  );
};

// 开始请求好友信息数据
const requestInfos = () => {
  if (showContent.value) showContent.value = false;
  if (isError.value) isError.value = false;
  isRequesting.value = true;
  friendStore
    .getFriendInfos({
      selfId: user.value.userId,
      otherId: props.userId,
    })
    .then((code: number) => {
      if (code === 1) {
        setInfo(props.userId);
        showContent.value = true;
        setTimeout(() => emits("updatePosition"));
      } else isError.value = true;
      isRequesting.value = false;
    })
    .catch(() => {
      isRequesting.value = false;
      isError.value = true;
    });
};

watch(
  () => props.userId,
  (newId: string, oldId, onInvalidate) => {
    if (newId) {
      onInvalidate(() => {
        if (isRequesting.value) {
          source.cancel();
          refreshAxios();
          isRequesting.value = false;
        }
      });
      if (props.userId === user.value.userId) {
        if (isError.value) isError.value = false;
        showContent.value = true;
      } else {
        if (friendStore.friendsInfos.has(props.userId)) {
          setInfo(props.userId);
          if (isError.value) isError.value = false;
          showContent.value = true;
        } else if (!isRequesting.value) requestInfos();
      }
    }
  },
  { immediate: true }
);

/**
 * 判断用户所点击的元素是否符合标准
 */
const judgeClick = (e: Event) => {
  const target: HTMLElement = e.target as HTMLElement;
  if (
    !isRequesting.value &&
    !userInfoRef.value?.contains(target) &&
    typeof target.className === "string" &&
    !target.className.includes("chatter-avatar") &&
    !target.className.includes("friManageFris-item__img") &&
    (!target.className.includes("sender-left") ||
      (target.className.includes("sender-left") && !props.isFriendDynamic)) &&
    !Object.is(target.dataset.name, "thuRemark")
  )
    emits("update:modelValue", false);
};

watch(
  () => props.modelValue,
  (newValue) => {
    if (newValue) document.addEventListener("click", judgeClick);
    else document.removeEventListener("click", judgeClick);
  }
);

/**
 * 是否显示操作菜单
 */
const showMenu = ref<boolean>(false);
const userInfoMenuRef = ref<HTMLDListElement>();

/**
 * 判断用户所点击的元素是否符合标准
 */
const judgeClickMenu = (e: Event) => {
  const target: HTMLElement = e.target as HTMLElement;
  if (
    !userInfoMenuRef.value?.contains(target) &&
    typeof target.className === "string" &&
    !target.className?.includes("recordUserInfo-more--icon")
  )
    showMenu.value = false;
};

watch(
  () => showMenu.value,
  (newValue) => {
    if (newValue) document.addEventListener("click", judgeClickMenu);
    else document.removeEventListener("click", judgeClickMenu);
  }
);

/**
 * 当前用户查看的图片的url
 */
const imgSrc = ref<string>("");
/**
 * 是否显示模态框
 */
const showModal = ref<boolean>(false);
// 浏览图片时打开模态框
const openModal: (url: string) => void = (url: string): void => {
  imgSrc.value = url;
  showModal.value = true;
};

/**
 * 是否打开设置菜单
 */
const showSetup = ref<boolean>(false);
/**
 * 设置的状态，0代表设置备注和标签，1代表设置朋友圈权限
 */
const setupState = ref<0 | 1>(0);
/**
 * 打开对好友设置对话框
 * @param type - 0代表设置备注和标签，1代表设置朋友圈权限
 */
const openSetup = (type: 0 | 1) => {
  setupState.value = type;
  showSetup.value = true;
  if (type === 0) {
    if (theInfoRemGroup.value.remark !== (userInfos.value as any).remark)
      theInfoRemGroup.value.remark = (userInfos.value as any).remark;
    if (theInfoRemGroup.value.group !== (userInfos.value as any).group)
      theInfoRemGroup.value.group = (userInfos.value as any).group;
  } else {
    if (
      theInfoPermission.value.disabledOtherLook !==
      (userInfos.value as any).disabledOtherLook
    )
      theInfoPermission.value.disabledOtherLook = (userInfos.value as any).disabledOtherLook;
    if (
      theInfoPermission.value.disabledSelfLook !==
      (userInfos.value as any).disabledSelfLook
    )
      theInfoPermission.value.disabledSelfLook = (userInfos.value as any).disabledSelfLook;
  }
};

// 修改好友信息成功后的操作
const success = (payload: {
  userId: string;
  type: 0 | 1;
  remark?: string;
  disabledSelfLook?: boolean;
}) => emits("success", payload);
</script>

<style lang="scss" scoped>
.fade {
  @include fade(0.15s, ease);
}

.recordUserInfo {
  position: absolute;
  top: 0;
  box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12);
  background-color: #fff;
  z-index: 1000;
  border-radius: 5px;
  padding: 15px 15px 12px;
  box-sizing: border-box;

  &-header {
    display: flex;
    align-items: flex-start;

    &__more {
      margin: -5px 0 0 5px;

      .recordUserInfo-more--icon {
        font-size: 24px;
        cursor: pointer;
      }
    }
  }

  &-main {
    position: relative;
    margin-top: 20px;
    font-size: 13px;
    color: #333;
    max-width: 230px;

    &__name {
      margin-right: 15px;
      color: rgba(128, 124, 124, 0.909);
      width: 55px;
      float: left;
    }

    &__tag {
      margin-top: 10px;
    }

    &__value {
      display: inline-block;
      max-width: 160px;
      word-break: break-all;
    }

    &::before {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      top: -10px;
      height: 1px;
      background-image: linear-gradient(
        to right,
        rgba(255, 0, 0, 0),
        #cec9c9,
        rgba(255, 0, 0, 0)
      );
    }
  }

  &-menu {
    @include opearMenu(1001, 12px);
    top: 12px;
    left: calc(100% - 10px);
    @include noselect();

    & > dt {
      padding: 5px 20px;
    }
  }

  &-loading {
    @include setWidHei(140px, 50px);

    .loadingIcon {
      font-size: 35px;
    }
  }

  &-error {
    @include setWidHei(140px, 50px);
    font-size: 13px;
    text-align: center;
    line-height: 50px;

    span {
      transition: color 0.2s;

      &:hover {
        cursor: pointer;
        color: rgb(250, 12, 12);
        text-decoration: underline;
      }
    }
  }
}
</style>
